package com.jier.common.permission;

import com.jier.common.exception.ErrorMessage;
import com.jier.common.util.PropertiesUtil;
import com.jier.entities.SystemModule;
import com.jier.entities.SystemRole;
import com.jier.entities.SystemUser;
import com.jier.enums.RoleType;
import com.jier.service.ISystemLogService;
import com.jier.service.ISystemModuleService;
import com.jier.service.ISystemRolePermissionService;
import com.jier.service.ISystemRoleService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author jie_r
 * @date 2018/03/25
 */
@Component
@Aspect
public class PermissionAspectHandle {
    /**
     * 项目登陆页
     */
    protected static String PROJECT_ADMIN_LOGIN;
    /**
     * 项目无权限页面
     */
    protected static String PROJECT_ADMIN_NO_PERMISSION;

    @Autowired
    private ISystemRolePermissionService systemRolePermissionService;

    @Autowired
    private ISystemRoleService systemRoleService;

    @Autowired
    private ISystemModuleService systemModuleService;

    public Object[] args = null;

    public PermissionAspectHandle() throws Exception {
        PROJECT_ADMIN_LOGIN = PropertiesUtil.getResStr("project.admin.page.login");
        PROJECT_ADMIN_NO_PERMISSION = PropertiesUtil.getResStr("project.admin.page.no.permission");
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void init() {
    }

    @Around("init()&&@annotation(requestMapping)&&@annotation(permission)")
    public Object validateAround(ProceedingJoinPoint joinPoint, RequestMapping requestMapping, Permission permission) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Object target = joinPoint.getTarget();
        Method method = this.getMethodByClassAndName(target.getClass(), methodName);
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        // 编号
        String permissionCode = permission.code();
        // 内容
        String permissionContent = permission.content();
        request.setAttribute("content", permissionContent);
        SystemUser systemUser = (SystemUser) request.getSession().getAttribute("currentUser");
        if (systemUser == null) {
            // 没有登陆 ==> 没有权限访问
            return error(method);
        }
        // 获取返回上一层数据
        SystemModule systemModule = systemModuleService.getSystemModuleByPermissionCode(permissionCode);
        request.setAttribute("systemModule", systemModule);
        SystemRole systemRole = systemRoleService.getSystemRole(systemUser.getId());
        if (systemRole.getType().equals(RoleType.normalAdmin.ordinal())) {
            // 获取权限
            boolean flag = systemRolePermissionService.getRolePermissionByCode(systemRole.getId(), permissionCode);
            if (!flag) {
                // 没权限禁止访问
                return error(method);
            }
        }
        return joinPoint.proceed();
    }

    public Object error(Method method) {
        Object returnObj = method.getReturnType();
        if (returnObj == ModelAndView.class) {
            // 没权限禁止访问
            ModelAndView mv = new ModelAndView(PROJECT_ADMIN_NO_PERMISSION);
            return mv;
        } else {
            return new ResponseEntity<ErrorMessage>(new ErrorMessage("没有权限访问"), HttpStatus.FORBIDDEN);
        }
    }

    public Object error(Method method, Map modelMap) {
        Object returnObj = error(method);
        if (returnObj.getClass() == ModelAndView.class) {
            // 没权限禁止访问
            ModelAndView mv = (ModelAndView) returnObj;
            mv.addAllObjects(modelMap);
        }
        return returnObj;
    }

    /**
     * 根据类和方法名得到方法
     */
    public Method getMethodByClassAndName(Class c, String methodName) {
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                return method;
            }
        }
        return null;
    }
}